package com.agg.persist.xml.util;

import com.agg.persist.xml.mapping.Property;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.expr.*;

import java.util.ArrayList;
import java.util.List;

public class ExprUtil {


    public  static  List<SQLPropertyExpr> getProperExprs(List<Property> properties, String p){
        List<SQLPropertyExpr> exprs= new ArrayList<>();
        for(Property property:properties){
            SQLPropertyExpr expr= getProperExpr(property.getName(),p);
            property.setExpr(expr);
            exprs.add(expr);
        }
        return exprs;
    }

    public  static   SQLPropertyExpr getProperExpr(String name,String group){
        SQLIdentifierExpr sqlIdentifierExpr = new SQLIdentifierExpr(group);
        SQLPropertyExpr sqlPropertyExpr = new SQLPropertyExpr(sqlIdentifierExpr, name);
        return sqlPropertyExpr;
    }
    public  static  SQLBinaryOpExpr getOnEqExpr(String leftVar, String leftOwner, String rightVar, String rightOwner){
        SQLBinaryOpExpr opExpr=new SQLBinaryOpExpr();
        opExpr.setOperator(SQLBinaryOperator.Equality);
        SQLIdentifierExpr sqlIdentifierExpr = new SQLIdentifierExpr(leftOwner);
        SQLPropertyExpr left = new SQLPropertyExpr(sqlIdentifierExpr, leftVar);
        sqlIdentifierExpr.setParent(left);
        opExpr.setLeft(left);
        SQLIdentifierExpr sqlIdentifierExpr2 = new SQLIdentifierExpr(rightOwner);
        SQLPropertyExpr right = new SQLPropertyExpr(sqlIdentifierExpr2, rightVar);
        sqlIdentifierExpr2.setParent(right);
        opExpr.setRight(right);
        return opExpr;
    }

    public  static    SQLBinaryOpExpr getEqExpr(String name,String owner){
        SQLBinaryOpExpr opExpr=new SQLBinaryOpExpr();
        opExpr.setOperator(SQLBinaryOperator.Equality);
        SQLIdentifierExpr sqlIdentifierExpr = new SQLIdentifierExpr(owner);
        SQLPropertyExpr left = new SQLPropertyExpr(sqlIdentifierExpr, "id");
        sqlIdentifierExpr.setParent(left);
        opExpr.setLeft(left);
        SQLIdentifierExpr sqlIdentifierExpr2 = new SQLIdentifierExpr("sku");
        SQLPropertyExpr right = new SQLPropertyExpr(sqlIdentifierExpr2, "product_id");
        sqlIdentifierExpr2.setParent(right);
        opExpr.setRight(right);
        return opExpr;
    }

    /**
     * 拼装，eq 比较
     * @param property
     * @param owner
     * @return
     */
    public  static    SQLBinaryOpExpr getEqExpr(Property property,String holer,String owner){
        SQLBinaryOpExpr opExpr=new SQLBinaryOpExpr();
        opExpr.setOperator(SQLBinaryOperator.Equality);
        SQLPropertyExpr left=getLeftExpr(property);
        opExpr.setLeft(left);
        SQLIdentifierExpr right= getRightExpr(property,holer);
        opExpr.setRight(right);
        return opExpr;
    }

    /**
     * 拼装，eq 比较
     * @param property
     * @param owner
     * @return
     */
    public  static  SQLBinaryOpExpr getEqValExpr(Property property,String owner,Object val){
        SQLBinaryOpExpr opExpr=new SQLBinaryOpExpr();
        opExpr.setOperator(SQLBinaryOperator.Equality);
        SQLPropertyExpr left=getLeftExpr(property);
        opExpr.setLeft(left);
        if(val instanceof  Number){
            SQLIntegerExpr right= new SQLIntegerExpr((Number) val);
            opExpr.setRight(right);
        }else{
            SQLCharExpr right= new SQLCharExpr(String.valueOf(val));
            opExpr.setRight(right);
        }

        return opExpr;
    }

    public  static  SQLBinaryOpExpr getEqValExpr(String name,String owner,Object val){
        SQLBinaryOpExpr opExpr=new SQLBinaryOpExpr();
        opExpr.setOperator(SQLBinaryOperator.Equality);
        SQLPropertyExpr left=getLeftExpr(owner,name);
        opExpr.setLeft(left);
        if(val instanceof  Number){
            SQLIntegerExpr right= new SQLIntegerExpr((Number) val);
            opExpr.setRight(right);
        }else{
            SQLCharExpr right= new SQLCharExpr(String.valueOf(val));
            opExpr.setRight(right);
        }

        return opExpr;
    }


    /**
     * 拼装，le 比较
     * @param property
     * @return
     */
    public  static    SQLBinaryOpExpr getLeExpr(Property property,String holer){
        SQLBinaryOpExpr opExpr=new SQLBinaryOpExpr();
        opExpr.setOperator(SQLBinaryOperator.LessThanOrEqual);
        SQLPropertyExpr left=getLeftExpr(property);
        opExpr.setLeft(left);
        SQLIdentifierExpr right= getRightExpr(property,holer);
        opExpr.setRight(right);
        return opExpr;
    }
    /**
     * 拼装，le 比较
     * @param property
     * @return
     */
    public  static    SQLBinaryOpExpr getLeExpr(Property property,String name,String holer){
        SQLBinaryOpExpr opExpr=new SQLBinaryOpExpr();
        opExpr.setOperator(SQLBinaryOperator.LessThanOrEqual);
        SQLPropertyExpr left=getLeftExpr(property);
        opExpr.setLeft(left);
        SQLIdentifierExpr right= getRightExpr(property,holer);
        opExpr.setRight(right);
        return opExpr;
    }

    /**
     * 拼装，ge 比较
     * @param property
     * @return
     */
    public  static    SQLBinaryOpExpr getGeExpr(Property property,String holer){
        SQLBinaryOpExpr opExpr=new SQLBinaryOpExpr();
        opExpr.setOperator(SQLBinaryOperator.GreaterThanOrEqual);
        SQLPropertyExpr left=getLeftExpr(property);
        opExpr.setLeft(left);
        SQLIdentifierExpr right= getRightExpr(property,holer);
        opExpr.setRight(right);
        return opExpr;
    }

    public  static SQLBinaryOpExpr getGeExpr(Property property,String name,String holer){
        SQLBinaryOpExpr opExpr=new SQLBinaryOpExpr();
        opExpr.setOperator(SQLBinaryOperator.GreaterThanOrEqual);
        SQLPropertyExpr left=getLeftExpr(property);
        opExpr.setLeft(left);
        SQLIdentifierExpr right= getRightExpr(name,holer);
        opExpr.setRight(right);
        return opExpr;
    }

    public  static SQLBinaryOpExpr getGeCharExpr(Property property,String value,String holer){
        SQLBinaryOpExpr opExpr=new SQLBinaryOpExpr();
        opExpr.setOperator(SQLBinaryOperator.GreaterThanOrEqual);
        SQLPropertyExpr left=getLeftExpr(property);
        opExpr.setLeft(left);
        SQLCharExpr right= getCharExpr(value);
        opExpr.setRight(right);
        return opExpr;
    }

    public  static SQLBinaryOpExpr getLeCharExpr(Property property,String value,String holer){
        SQLBinaryOpExpr opExpr=new SQLBinaryOpExpr();
        opExpr.setOperator(SQLBinaryOperator.LessThanOrEqual);
        SQLPropertyExpr left=getLeftExpr(property);
        opExpr.setLeft(left);
        SQLCharExpr right= getCharExpr(value);
        opExpr.setRight(right);
        return opExpr;
    }
    /**
     * 拼装，like 比较
     * @param property
     * @return
     */
    public  static SQLBinaryOpExpr getLikeExpr(Property property,String holer){
        SQLBinaryOpExpr opExpr=new SQLBinaryOpExpr();
        opExpr.setOperator(SQLBinaryOperator.Like);
        SQLPropertyExpr left=getLeftExpr(property);
        opExpr.setLeft(left);
        SQLIdentifierExpr right= getRightExpr(property,holer);
        SQLIdentifierExpr likeExpr= wrapRightLikeExpr(right.toString());
        opExpr.setRight(likeExpr);
        return opExpr;
    }

    /**
     * 拼装，like 比较
     * @param property
     * @return
     */
    public  static    SQLBinaryOpExpr getLikeExpr(Property property,String varName,String holer){
        SQLBinaryOpExpr opExpr=new SQLBinaryOpExpr();
        opExpr.setOperator(SQLBinaryOperator.Like);
        SQLPropertyExpr left=getLeftExpr(property);
        opExpr.setLeft(left);
        SQLIdentifierExpr right= getRightExpr(varName,holer);
        SQLIdentifierExpr likeExpr= wrapRightLikeExpr(right.toString());
        opExpr.setRight(likeExpr);
        return opExpr;
    }
    /**
     * 拼装左侧变量，例如：p.product_name 的变量
     * @param property
     * @return
     */
    public  static    SQLPropertyExpr getLeftExpr(Property property){
        SQLIdentifierExpr sqlIdentifierExpr = new SQLIdentifierExpr(property.getOwner());
        SQLPropertyExpr left = new SQLPropertyExpr(sqlIdentifierExpr, property.getColumn());
        sqlIdentifierExpr.setParent(left);
        return left;
    }

    /**
     * 拼装左侧变量，例如：p.product_name 的变量
     * @param owner
     * @param name
     * @return
     */
    public  static  SQLPropertyExpr getLeftExpr(String owner, String name){
        SQLIdentifierExpr sqlIdentifierExpr = new SQLIdentifierExpr(owner);
        SQLPropertyExpr left = new SQLPropertyExpr(sqlIdentifierExpr, name);
        sqlIdentifierExpr.setParent(left);
        return left;
    }
    /**
     * 拼装，例如：#{cm.name} 的变量
     * @param property
     * @param holer
     * @return
     */
    public  static    SQLIdentifierExpr getRightExpr(Property property, String holer){
        String paramTpl="#{%s.%s}";
        String paramVar=String.format(paramTpl,holer,property.getName());
        SQLIdentifierExpr  right = new SQLIdentifierExpr (paramVar);
        return right;
    }

    /**
     * 拼装，例如：#{cm.name} 的变量
     * @param varName
     * @param holer
     * @return
     */
    public  static  SQLIdentifierExpr getRightExpr(String varName,String holer){
        String paramTpl="#{%s.%s}";
        String paramVar=String.format(paramTpl,holer,varName);
        SQLIdentifierExpr  right = new SQLIdentifierExpr (paramVar);
        return right;
    }

    /**
     * 拼装 字符串
     * @return
     */
    public  static SQLCharExpr getCharExpr(String val){
        SQLCharExpr  c = new SQLCharExpr (val);
        return c;
    }

    public  static  SQLIdentifierExpr wrapRightLikeExpr(String paramVar){
        String likeStr="CONCAT('%', "+paramVar+", '%')";
        SQLIdentifierExpr  right = new SQLIdentifierExpr (likeStr);
        return right;
    }

    public static SQLInListExpr inExpr(String owner,String name,List list){
        SQLBinaryOpExpr opExpr=new SQLBinaryOpExpr();
        SQLIdentifierExpr sqlIdentifierExpr = new SQLIdentifierExpr(owner);
        SQLPropertyExpr left = new SQLPropertyExpr(sqlIdentifierExpr, name);
        opExpr.setOperator(SQLBinaryOperator.BooleanAnd);
        opExpr.setLeft(left);

        SQLInListExpr  sqlInListExpr = new SQLInListExpr(left);
        // 构造 in 内包含的东西
        List<SQLExpr> refExprList = new ArrayList<>();
        for (Object o:list) {
            if(o instanceof  Number){
                SQLIntegerExpr expr = new SQLIntegerExpr((Number) o);
                refExprList.add(expr);
            }else{
                SQLCharExpr sqlCharExpr = new SQLCharExpr(String.valueOf(o));
                refExprList.add(sqlCharExpr);
            }


        }
        sqlInListExpr.setTargetList(refExprList);
        opExpr.setRight(sqlInListExpr);
        return sqlInListExpr;
    }

    public static SQLInListExpr inIdsExpr(String owner,List<Long> ids){
        SQLBinaryOpExpr opExpr=new SQLBinaryOpExpr();
        SQLIdentifierExpr sqlIdentifierExpr = new SQLIdentifierExpr(owner);
        SQLPropertyExpr left = new SQLPropertyExpr(sqlIdentifierExpr, "id");
        opExpr.setOperator(SQLBinaryOperator.BooleanAnd);
        opExpr.setLeft(left);

        SQLInListExpr  sqlInListExpr = new SQLInListExpr(left);
        // 构造 in 内包含的东西
        List<SQLExpr> refExprList = new ArrayList<>();
        for (Long id:ids) {
            SQLIntegerExpr expr = new SQLIntegerExpr(id);
            refExprList.add(expr);
        }
        sqlInListExpr.setTargetList(refExprList);
        opExpr.setRight(sqlInListExpr);
        return sqlInListExpr;
    }



}
